home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / Palettes / TTools / TToolsPalette / TBinderList.subproj / TBinder.m < prev    next >
Encoding:
Text File  |  1995-06-12  |  6.6 KB  |  197 lines

  1. /* TBinder.m
  2.  * Written By:  Thomas Burkholder
  3.  *
  4.  * You may freely copy, distribute, and reuse the code in this example.
  5.  * NeXT disclaims any warranty of any kind, expressed or  implied, as to its
  6.  * fitness for any particular use.
  7.  */
  8.  
  9. #import "TBinder.h"
  10.  
  11. @implementation TBinder
  12.  
  13. int returnsDouble(id oClass, SEL aSelector)
  14. {
  15.     struct objc_method *p = class_getInstanceMethod(oClass,aSelector);
  16.     
  17.     if ((p->method_types) && (p->method_types[0]=='d'))
  18.         return 1;
  19.     return 0;
  20. }
  21.  
  22. int takesDouble(id oClass, SEL aSelector)
  23. {
  24.     // modifiers always look like : "@16@8:12d16"
  25.     struct objc_method *p = class_getInstanceMethod(oClass,aSelector);
  26.     
  27.     if ((p->method_types) && (p->method_types[8]=='d'))
  28.         return 1;
  29.     return 0;
  30. }
  31.  
  32. int returnsFloat(id oClass, SEL aSelector)
  33. {
  34.     // modifiers always look like : "@16@8:12d16"
  35.     struct objc_method *p = class_getInstanceMethod(oClass,aSelector);
  36.     
  37.     if ((p->method_types) && (p->method_types[0]=='f'))
  38.         return 1;
  39.     return 0;
  40. }
  41.  
  42. int takesFloat(id oClass, SEL aSelector)
  43. {
  44.     struct objc_method *p = class_getInstanceMethod(oClass,aSelector);
  45.     
  46.     if ((p->method_types) && (p->method_types[8]=='f'))
  47.         return 1;
  48.     return 0;
  49. }
  50.  
  51. - init
  52. {
  53.     [super init];
  54.     dataSource = nil;
  55.     interface = nil;
  56.     interfaceAccessor = (SEL)0;
  57.     interfaceModifier = (SEL)0;
  58.     dataSourceAccessor = (SEL)0;
  59.     dataSourceModifier = (SEL)0;
  60.     flags.verify = NO;
  61.     flags.autoUpdate = YES;
  62.     return self;
  63. }
  64.  
  65. - setTarget:anObject { target = anObject; return self; }
  66. - target { return target; }
  67. - setAction:(SEL)anAction { action = anAction; return self; }
  68. - (SEL)action { return action; }
  69. - setDataSource:anObject { dataSource = anObject; return self; }
  70. - dataSource { return dataSource; }
  71. - setInterface:anObject { interface = anObject; return self; }
  72. - interface { return interface; }
  73. - setInterfaceAccessor:(SEL)aSel { interfaceAccessor = aSel; return self; }
  74. - (SEL)interfaceAccessor { return interfaceAccessor; }
  75. - setInterfaceModifier:(SEL)aSel { interfaceModifier = aSel; return self; }
  76. - (SEL)interfaceModifier { return interfaceModifier; }
  77. - setDataSourceAccessor:(SEL)aSel { dataSourceAccessor = aSel; return self; }
  78. - (SEL)dataSourceAccessor { return dataSourceAccessor; }
  79. - setDataSourceModifier:(SEL)aSel { dataSourceModifier = aSel; return self; }
  80. - (SEL)dataSourceModifier { return dataSourceModifier; }
  81. - setVerify:(BOOL)yn { flags.verify = yn; return self; }
  82. - (BOOL)verify { return flags.verify; }
  83. - setAutoUpdate:(BOOL)yn { flags.autoUpdate = yn; return self; }
  84. - (BOOL)autoUpdate { return flags.autoUpdate; }
  85.  
  86. - updateInterface:sender
  87. {
  88.     double (*doubleAcc)(id,SEL);
  89.     float (*floatAcc)(id,SEL);
  90.     id (*doubleMod)(id,SEL,double);
  91.     id (*floatMod)(id,SEL,float);
  92.     float f;
  93.     double d;
  94.  
  95.     // objc_msgSend is stupid about returning float and double...
  96.     if (returnsDouble([dataSource class], dataSourceAccessor)) {
  97.         doubleAcc = (double (*)(id,SEL))[dataSource methodFor:dataSourceAccessor];
  98.         d = doubleAcc(dataSource, dataSourceAccessor);
  99.         if (takesDouble([interface class], interfaceModifier)) {
  100.             doubleMod = (id (*)(id,SEL,double))[interface methodFor:interfaceModifier];
  101.             doubleMod(interface,interfaceModifier,d);
  102.         } else if (takesFloat([interface class], interfaceModifier)) {
  103.             floatMod = (id (*)(id,SEL,float))[interface methodFor:interfaceModifier];
  104.             floatMod(interface,interfaceModifier,(float)d);
  105.         } else {  // passing a float or a double to something that won't take it.
  106.             fprintf(stderr,"TBinder: attempt to bind double to non-float/double\n");
  107.         }
  108.     } else if (returnsFloat([dataSource class], dataSourceAccessor)) {
  109.         floatAcc = (float (*)(id,SEL))[dataSource methodFor:dataSourceAccessor];
  110.         f = floatAcc(dataSource, dataSourceAccessor);
  111.         if (takesFloat([interface class], interfaceModifier)) {
  112.             floatMod = (id (*)(id,SEL,float))[interface methodFor:interfaceModifier];
  113.             floatMod(interface,interfaceModifier,f);
  114.         } else if (takesDouble([interface class],interfaceModifier)) {
  115.             doubleMod = (id (*)(id,SEL,double))[interface methodFor:interfaceModifier];
  116.             doubleMod(interface,interfaceModifier,(double)f);
  117.         } else {
  118.             fprintf(stderr,"TBinder: attempt to bind float to non-float/double\n");
  119.         }
  120.     } else {  // Should cover ordinary stuff.
  121.         objc_msgSend(interface,interfaceModifier,[dataSource perform:dataSourceAccessor]);
  122.     }
  123.     return self;
  124. }
  125.  
  126. - updateDataSource:sender
  127. {
  128.     double (*doubleAcc)(id,SEL);
  129.     id (*doubleMod)(id,SEL,double);
  130.     float (*floatAcc)(id,SEL);
  131.     id (*floatMod)(id,SEL,float);
  132.     float f;
  133.     double d;
  134.  
  135.     if (target && action) {
  136.         [target perform:action with:sender];
  137.     }
  138.     // objc_msgSend is stupid about returning float and double...
  139.     if (returnsDouble([interface class], interfaceAccessor)) {
  140.         doubleAcc = (double (*)(id,SEL))[interface methodFor:interfaceAccessor];
  141.         d = doubleAcc(interface, interfaceAccessor);
  142.         if (takesDouble([dataSource class],dataSourceModifier)) {
  143.             doubleMod = (id (*)(id,SEL,double))[dataSource methodFor:dataSourceModifier];
  144.             doubleMod(dataSource,dataSourceModifier,d);
  145.         } else if (takesFloat([dataSource class],dataSourceModifier)) {
  146.             floatMod = (id (*)(id,SEL,float))[dataSource methodFor:dataSourceModifier];
  147.             floatMod(dataSource,dataSourceModifier,(float)d);
  148.         } else {
  149.             fprintf(stderr,"TBinder: attempt to bind double to non-float/double\n");
  150.         }
  151.     } else if (returnsFloat([interface class], interfaceAccessor)) {
  152.         floatAcc = (float (*)(id,SEL))[interface methodFor:interfaceAccessor];
  153.         f = floatAcc(interface, interfaceAccessor);
  154.         if (takesFloat([dataSource class],dataSourceModifier)) {
  155.             floatMod = (id (*)(id,SEL,float))[dataSource methodFor:dataSourceModifier];
  156.             floatMod(dataSource,dataSourceModifier,f);
  157.         } else if (takesDouble([dataSource class],dataSourceModifier)) {
  158.             doubleMod = (id (*)(id,SEL,double))[dataSource methodFor:dataSourceModifier];
  159.             doubleMod(dataSource,dataSourceModifier,(double)f);
  160.         } else {
  161.             fprintf(stderr,"TBinder: attempt to bind float to non-float/double\n");
  162.         }
  163.     } else {  // Should cover ordinary stuff.
  164.         objc_msgSend(dataSource,dataSourceModifier,[interface perform:interfaceAccessor]);
  165.     }
  166.     if (flags.verify) {
  167.         [self updateInterface:sender];
  168.     }
  169.     return self;
  170. }
  171.  
  172. - read:(NXTypedStream *)stream
  173. {
  174.     [super read:stream];
  175.     dataSource = NXReadObject(stream);
  176.     interface = NXReadObject(stream);
  177.     target = NXReadObject(stream);
  178.     NXReadTypes(stream,":::::c",&action,&interfaceAccessor,
  179.                 &interfaceModifier,&dataSourceAccessor,
  180.                 &dataSourceModifier, &flags);
  181.     return self;
  182. }
  183.  
  184. - write:(NXTypedStream *)stream
  185. {
  186.     [super write:stream];
  187.     NXWriteObject(stream, dataSource);
  188.     NXWriteObject(stream, interface);
  189.     NXWriteObject(stream, target);
  190.     NXWriteTypes(stream,":::::c",&action,&interfaceAccessor,
  191.                 &interfaceModifier,&dataSourceAccessor,
  192.                 &dataSourceModifier,&flags);
  193.     return self;
  194. }
  195.  
  196. @end
  197.